Repository navigation
Capture new Claude Code hook fields (effort, duration_ms, is_interrupt) - #200
Abhijeet Prasad (AbhiPrasad) wants to merge 2 commits into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 552e777d85
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".
| if let Some(effort) = &hook.effort { | ||
| self.effort = Some(effort.clone()); |
There was a problem hiding this comment.
Update the active turn when effort first appears
Claude does not consistently include effort on UserPromptSubmit: for example, subagent-compact/events.ndjson line 2 omits it and the corresponding Stop on line 4 reports high. Because open_turn snapshots self.effort only when the turn opens, this assignment merely caches the late value for the next turn and never adds it to the turn that produced the hook. Consequently, the first turn loses known effort metadata, and after an effort change a later turn can retain the previous level until another turn opens; merge newly observed effort into the currently active turn as well.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good catch, fixed in 8e34e04. The recorded fixtures confirm that UserPromptSubmit never carries effort; it only arrives on later hooks. Each turn now tracks the level it has recorded, and a newly observed level is merged into the active turn (record_turn_effort). The real-fixture test now asserts that every turn gets xhigh.
Record effort.level on turn spans, and duration_ms / is_interrupt on tool spans. Effort is decoded through HookContext alongside permission_mode, and duration_ms is read once per tool completion so span timing and metadata agree. Consolidate overlapping Claude translator tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude Code omits effort on UserPromptSubmit and reports it on later hooks (Stop, PreToolUse, PostToolUse). Snapshotting effort only when a turn opened left the first turn without it and let later turns carry a stale level. Track the level each turn recorded and merge a newly observed one into the active turn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
af2f4a7 to
e6bf913
Compare
|
Some conflicts to address. |
What was missing
Claude Code hooks now send more input fields; the same set showed up in claude-agent-sdk 0.2.166 (braintrustdata/braintrust-sdk-python#973). The Claude Code translator reads payload fields directly instead of going through an allowlist, so
last_assistant_message,error, andprompt_idwere already being used. Three fields were still dropped:effort({"level": "high"})duration_msstart_mswhen there was no PreToolUse, never recordedis_interruptThe fix
Effort → turn metadata.
effortis decoded inHookContextand tracked inobserve_session_detailstogether withpermission_mode. Claude Code doesn't sendeffortonUserPromptSubmit; it shows up on later hooks (Stop, PreToolUse, PostToolUse). So reading it only when a turn opens isn't enough. Each turn tracks the level it has recorded, and when a different level arrives it is merged into the active turn:Tool timing / interrupts → tool metadata.
finish_toolreadsduration_msonce. That one value sets bothnative_duration_ms(the key the Cursor translator already uses) and the fallback start time, so the span timing and the metadata can't disagree:Span timing doesn't change when PreToolUse exists: the span still runs from PreToolUse to PostToolUse.
prompt_idcomment. The old comment said native hooks never sendprompt_id. They now send it after the first user input, though older Claude Code versions leave it out. The matching code already handled both cases, so only the comment changed.Test cleanup
The Claude translator tests went from 33 to 29 by merging overlapping cases: the three root-output tests, the two SubagentStart-validation tests, and the success and failure tool-outcome tests. Hand-built
Envelopeliterals were replaced with the existingclaude_eventhelper.🤖 Generated with Claude Code